package com.cyw.common.utils.http;

import com.cyw.common.utils.JsonUtils;
import com.cyw.common.utils.LogUtils;
import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.protocol.HttpContext;

import java.util.Map;
import java.util.StringJoiner;

/**
 * 请求参数
 */
public class HttpRequest {

    /**
     * 请求地址
     */
    private String url;
    /**
     * 查询字符串键值对（GET，查询字符串也可以放到url中）
     * 请求实体参数键值对（POST)
     * json键值对（POST_JSON）
     */
    private Map<String, Object> params;
    /**
     * 请求实体，需配合POST_ENTITY使用
     * 如果传了这个参数，params就不再作为请求实体参数了
     */
    private HttpEntity entity;

    /**
     * 自定义请求头
     */
    private Map<String, String> headerMap;

    /**
     * 自定义客户端
     */
    private CloseableHttpClient client;

    /**
     * 请求方法
     */
    private HttpMethod httpMethod;

    /**
     * 自定义HttpContext
     */
    private HttpContext httpContext;

    private HttpRequest() {
    }

    public static HttpRequest newHttpRequest(String url) {
        HttpRequest httpRequest = new HttpRequest();
        httpRequest.url = url;
        httpRequest.httpMethod = HttpMethod.GET;
        return httpRequest;
    }

    public HttpRequest withUrl(String url) {
        this.url = url;
        return this;
    }

    public HttpRequest withParams(Map<String, Object> params) {
        this.params = params;
        return this;
    }

    public HttpRequest withHeaderMap(Map<String, String> headerMap) {
        this.headerMap = headerMap;
        return this;
    }

    public HttpRequest withClient(CloseableHttpClient client) {
        this.client = client;
        return this;
    }

    public HttpRequest withHttpMethod(HttpMethod httpMethod) {
        this.httpMethod = httpMethod;
        return this;
    }

    public HttpRequest withHttpContext(HttpContext httpContext) {
        this.httpContext = httpContext;
        return this;
    }

    public HttpRequest withEntity(HttpEntity entity) {
        this.entity = entity;
        this.httpMethod = HttpMethod.POST_ENTITY;
        return this;
    }

    public String getUrl() {
        return url;
    }

    public Map<String, Object> getParams() {
        return params;
    }

    public Map<String, String> getHeaderMap() {
        return headerMap;
    }

    public CloseableHttpClient getClient() {
        return client;
    }

    public HttpMethod getHttpMethod() {
        return httpMethod;
    }

    public HttpContext getHttpContext() {
        return httpContext;
    }

    public HttpEntity getEntity() {
        return entity;
    }

    @Override
    public String toString() {
        return new StringJoiner(", ", "{", "}")
                .add("\"httpMethod\":\"" + httpMethod + "\"")
                .add("\"url\":\"" + url + "\"")
                .add("\"params\":" + JsonUtils.toJson(params))
                .add("\"headerMap\":" + JsonUtils.toJson(headerMap))
                .add("\"cookies\":" + getCookieStore())
                .add("\"httpContext\":\"" + httpContext + "\"")
                .add("\"entity\":\"" + getEntityStr() + "\"")
                .add("\"client\":\"" + client + "\"")
                .toString();
    }

    private String getEntityStr() {
        if (entity == null) {
            return null;
        }
        try {
            if (entity instanceof StringEntity) {
                StringEntity stringEntity = (StringEntity) this.entity;
                byte[] bytes = IOUtils.toByteArray(stringEntity.getContent());

                String charset = "UTF-8";
                Header contentEncoding = stringEntity.getContentEncoding();
                if (contentEncoding == null) {
                    HeaderElement[] elements = stringEntity.getContentType().getElements();
                    if (elements.length > 0) {
                        NameValuePair nameValuePair = elements[0].getParameterByName("charset");
                        if (nameValuePair != null) {
                            charset = nameValuePair.getValue();
                        }
                    }
                } else {
                    charset = contentEncoding.getValue();
                }
                return new String(bytes, charset);
            }
        } catch (Exception e) {
            LogUtils.printError(e);
        }
        return entity.toString();
    }

    private String getCookieStore() {
        String empty = "\"\"";
        try {
            if (httpContext != null) {
                Object cookieStore = httpContext.getAttribute(HttpClientContext.COOKIE_STORE);
                if (cookieStore != null) {
                    return JsonUtils.toJson(cookieStore);
                }
            }
            return empty;
        } catch (Exception e) {
            LogUtils.printError(e);
            return empty;
        }
    }

    public enum HttpMethod {
        GET,
        POST,        //post实体是urlencodeform格式的键值对
        POST_JSON,   //post实体是json，json字符串由params参数转换而来
        POST_ENTITY, //自定义post实体，比如urlencodeform(同POST), json（同POST_JSON），xml
        DELETE,
        PUT
    }
}